package server.thread;

import server.http.*;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import server.piles.Piles;

/**
 *
 * @author Sérgio C. Peres
 * @author Guilherme Alves
 */
public class HTTPResponse
{
    private HTTPServer server;
    private DataOutputStream output;
    private String addressReq;
    private boolean isNotGETRequest;
    
    protected static final DateFormat HTTP_DATE_FORMAT = new SimpleDateFormat(
            "EEE, dd MMM yyyy HH:mm:ss z");

    public HTTPResponse(HTTPServer srv, DataOutputStream output)
    {
        this.output = output;
        this.server = srv;
        this.isNotGETRequest = false;
    }

    public boolean setRequest(String request, String addressReq)
    {
        try
        {            
            if (!request.equalsIgnoreCase("GET") && !request.equalsIgnoreCase("POST"))
            {
                this.isNotGETRequest = true;
            }
            else
            {
                this.addressReq = addressReq;
            }
        } catch (StringIndexOutOfBoundsException e)
        {
            return false;
        }
        return true;
    }

    public void sendResponse(Request request, Piles pilha) throws IOException
    {
        if (!this.isNotGETRequest){
            if (request.getMethod().equalsIgnoreCase("GET")) {
                this.readFile();
            } else {
                if (request.getMethod().equalsIgnoreCase("POST")) {
                    String reslt = this.opPiles(pilha,request);
                    this.postFile(request,reslt);
                }
            }
        }
        else
        {
            output.writeBytes(returnHTMLError(400, null));
        }
        output.close();
    }

    public void readFile() throws IOException
    {
        FileReader in;
        try
        {
            in = new FileReader(this.server.getPathDir() + "\\" + 
                    ((this.addressReq.length() != 1) ? this.addressReq.trim().substring(1) : "index.html"));
            try
            {
                output.write(getHead("200 OK",defineTipo(addressReq.trim())).getBytes());
                   
                int i;
                for (i = in.read(); i != -1; i = in.read())
                {
                    output.writeByte(i);
                }
                in.close();
            } catch (IOException ex)
            {
                output.writeBytes(returnHTMLError(500, this.addressReq));
            }
        } catch (FileNotFoundException ex)
        {
            output.writeBytes(returnHTMLError(404, this.addressReq));
        }
    }
    
    public void postFile(Request request, String result) throws IOException
    {
        FileReader in;
        try
        {
            try
            {
                if (addressReq.length() == 1) {
                    output.write(pagePostMessagem(request,result).getBytes());
                } else {    
                    in = new FileReader(this.server.getPathDir() + "\\" + 
                        ((this.addressReq.length() != 1) ? this.addressReq.trim().substring(1) : "index.html"));
                    
                    output.write(getHead("200 OK",defineTipo(addressReq.trim())).getBytes());

                    int i;
                    for (i = in.read(); i != -1; i = in.read())
                    {
                        output.writeByte(i);
                    }
                    in.close();
                }
            } catch (IOException ex)
            {
                output.writeBytes(returnHTMLError(500, this.addressReq));
            } finally {
                output.close();
            }
            
        } catch (FileNotFoundException ex)
        {
            output.writeBytes(returnHTMLError(404, this.addressReq));
        } finally {
            output.close();
        }
    }

    private String returnHTMLError(int errorCode, String req)
    {
        String title, h1, messengerError;
        title = h1 = messengerError = "";
        String res = "";
        
        switch (errorCode)
        {
            case 404:
                res = getHead("404 Not found","text/html; charset=UTF-8");
                title = "404 Not Found";
                h1 = "Not Found";
                messengerError = "        <p>The requested URL " + req + " was not found on this server.</p>\n"
                        + "        <p>\n"
                        + "            Additionally, a 404 Not Found\n"
                        + "            terror was encountered while trying to use an ErrorDocument to handle the request.\n"
                        + "        </p>\n";
                break;
                
            case 400:
                res = getHead("400 Bad request","text/html; charset=UTF-8");
                title = "400 Bad Request";
                h1 = "Bad Request";
                break;
                
            default:
                res = getHead("500 Internal Server Error","text/html; charset=UTF-8");
                title = "500 Internal Server Error";
                h1 = "Internal Server Error";
                messengerError = "        <br /><br />\n"
                        + "        <h3>\n"
                        + "            <marquee>Sorry! Server error...  :'(</marquee>\n"
                        + "        </h3>\n"
                        + "        <br /><br />\n";
                break;
        }
        
        res += "<!DOCTYPE html>\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
                + "    <head>\n"
                + "        <title>" + title + "</title>\n"
                + "    </head>\n"
                + "    <body>\n"
                + "        <h1>" + h1 + "</h1>\n"
                + "        <!-- Messenger error! -->\n\n"
                + messengerError
                + "\n\n        <!-- Fim messenger error -->\n"
                + "        <hr />\n"
                + "        <address>Web Server at " + "" + " Port " + this.server.getPort() + "</address>\n"
                + "    </body>\n"
                + "</html>";
        return res;
    }
    
    private String getHead(String codErro,String tipoRequisicao) {
        // Head
        StringBuilder sb = new StringBuilder();
        // Cria primeira linha do status code, no caso 200 OK
        sb.append("HTTP/1.1 " + codErro).append("\r\n");

        // Cria os cabeçalhos
        sb.append("Date: ").append(HTTP_DATE_FORMAT.format(new Date()))
                .append("\r\n");
        sb.append("Server: Web Server")
                .append("\r\n");
        sb.append("Connection: Close").append("\r\n");
        sb.append("Content-Type: " + tipoRequisicao).append("\r\n");
        sb.append("\r\n");
        return sb.toString();
    }
    
    private String defineTipo(String file) {
        /**
         * Mais tipo acesse em:
         * http://en.wikipedia.org/wiki/MIME_type#List_of_common_media_subtype_prefixes
         */
        String tipo = "";
        int i = (file.length() - 1);
        for ( ; i > 0;  i--) {
            if (file.charAt(i) == '.') {
                break;
            }
        }
        
        System.out.println("»»» Tipo do arquivo requisitado: "+file.substring(i));
        switch(file.substring(i)) {
            // tipo de Arquivos
            case ".http": tipo = "text/html; charset=UTF-8"; break;
            case ".css" : tipo = "text/css; charset=UTF-8"; break;
            case ".js" : tipo = "text/javascript; charset=UTF-8"; break;
            // tipos de Imagens
            case ".gif": tipo = "image/gif;"; break;
            case ".jpg" : tipo = "image/jpeg;"; break;
            case ".jpeg" : tipo = "image/jpeg;"; break;
            case ".png": tipo = "image/png"; break;
            
            default: tipo = "text/html; charset=UTF-8";
        }
        return tipo;
    }
    
    private String pagePostRepley(Request request) {
        String messenger = "";
        String res = getHead("200 OK", addressReq);
        String data = request.getData();
        
        String[] msn = request.getData().split("&");
        
        for (int i = 0; i < msn.length; i++) {
            System.out.println("msn: " + msn[i] + "; i: " + i);
            String[] m = msn[i].split("=");
            messenger += 
                    "                <tr>\n"
                  + "                    <td>" + m[0] + "</td>\n"
                  + "                    <td>" + m[1] + "</td>\n"
                  + "                </tr>\n";           
        }
        
        res += "<!DOCTYPE html>\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
                + "    <head>\n"
                + "        <title>Resposta - Post</title>\n"
                + "    </head>\n"
                + "    <body>\n"
                + "        <h1>Dados enviados com sucesso !!!</h1>\n"
                
                + "        <table border=\"1\" width=\"8\">\n"
                + "            <thead>\n"
                + "                <tr>\n"
                + "                    <th>Parametros</th>\n"
                + "                    <th>Dados</th>\n"
                + "                </tr>\n"
                + "            </thead>\n"
                + "            <tbody>\n"
                
                + messenger
                
                + "            </tbody>\n"
                + "        </table>\n"
                
                + "    </body>\n"
                + "</html>";
        
        return res;
    }
    
    private String pagePostMessagem(Request request, String resut) {
        String messenger = "";
        String res = getHead("200 OK", addressReq);
        String data = request.getData();
        
        String[] msn = request.getData().split("&");
        
        for (int i = 0; i < msn.length; i++) {
            System.out.println("msn: " + msn[i] + "; i: " + i);
            String[] m = msn[i].split("=");
            messenger += 
                    "                <tr>\n"
                  + "                    <td>" + m[0] + "</td>\n"
                  + "                    <td>" + m[1] + "</td>\n"
                  + "                </tr>\n";           
        }
        
        res += "<!DOCTYPE html>\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
                + "    <head>\n"
                + "        <title>Resposta - Post</title>\n"
                + "    </head>\n"
                + "    <body>\n"
                + "        <h1>Resultado</h1>\n"
                
                + "        <h3>Resultado da operação:</h3>\n"
                + "        <p>\n"
                + resut
                + "\n        </p>\n"
                
                + "        <br /><br />\n"
                + "        <h3>Resultado momandos</h3>\n"
                + "        <table border=\"1\">\n"
                + "            <thead>\n"
                + "                <tr>\n"
                + "                    <th>Campo</th>\n"
                + "                    <th>Parametro</th>\n"
                + "                </tr>\n"
                + "            </thead>\n"
                + "            <tbody>\n"
                
                + messenger
                
                + "            </tbody>\n"
                + "        </table>\n"
                
                + "    </body>\n"
                + "</html>";
        
        return res;
    }
    
    private String[] action(String data) {
        return data.split("&");
    }
    
    private String opPiles(Piles pilha, Request request) {
//        action=criar&name=PILHA‏
//        ‎action=zerar&name=PILHA‏
//        action=push&name=PILHA&data=TEXTO‏
//        action=pop&name=PILHA‏
//        action=dump&name=PILHA‏
        PilesAction pa = new PilesAction();
        pa.setPilesAction(request.getData());
        
        String msn = "Erro... A operação \"" + pa.getAction() + "\" não pode ser executada!!!";
        if (pa.getAction().equalsIgnoreCase("criar")) {
            if (pilha.create(pa.getName())) {
                msn = "Pilha criada com sucesso... [" + pa.getName() + "]";
            }
        } else {
            if (pa.getAction().equalsIgnoreCase("zerar")) {
                if (pilha.reset(pa.getName())) {
                    msn = "Pilha zerada com sucesso... [" + pa.getName() + "]";
                }
            } else {
                if (pa.getAction().equalsIgnoreCase("push") && !pa.isEmptyData()) {
                    String push = (String) pilha.push(pa.getData(),pa.getData());
                    if (push.equalsIgnoreCase(pa.getData())) {
                        msn = "Push executado com sucesso... [" + pa.getName() + "]";
                    }
                } else {
                    if (pa.getAction().equalsIgnoreCase("pop")) {
                        msn = "Pop - resultado: " + (String) pilha.pop(pa.getName());
                    } else {
                        if (pa.getAction().equalsIgnoreCase("dump")) {
                            String[] dump = pilha.dump(pa.getName());
                            msn = "";
                            for (int i = 0; i < dump.length; i++) {
                                msn += dump[i] + "\n";
                            }
                        }
                    }
                }
            }
        }
        return msn;
    }
}